package com.example.bootdemo.function;

import com.example.bootdemo.atomic.Cat;
import org.junit.Test;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public class FunctionalInterfaceDemo {
    public static void main(String[] args) {

    }

    /**
     * Comsumer<T>消费型接口：
     * 表示接受单个输入参数但不返回结果的操作，
     * 包含方法：void accept(T t)，
     * 可以理解为消费者，只消费（接收单个参数）、不返回（返回为 void）；
     */
    @Test
    public void consumerDemo1() {
        Consumer<String> consumer = s -> System.out.println(s);
        consumer.accept("只消费，不返回");
    }

    /**
     * Supplier<T>供给型接口：表示结果的供给者，包含方法T get()，
     * 可以理解为供给者，只提供（返回T类型对象）、不消费（不接受参数）；
     */
    @Test
    public void supplierDemo1() {
        Supplier<String> supplier = () -> "只返回，不消费";
        String s = supplier.get();
        System.out.println(s);
    }

    /**
     * Function<T, R>函数型接口：
     * 表示接受一个T类型参数并返回R类型结果的对象，
     * 包含方法R apply(T t)；
     */
    @Test
    public void FunctionDemo1() {
        //定义一个String类型的整数
        //  String a = "1234";
        //调用change方法，将String类型的整数转换为Integer类型的整数，使用Lambda接口
       /* change(a, (String str) -> {
            return Integer.parseInt(str);
        });*/
        int a = 6;

        //优化Lambda
        int in = change1(a, str -> a * a);
        System.out.println(in);

    }

    /*
     定义一个方法
     方法的参数传递一个字符串类型的整数
     方法的参数传递一个Function接口，泛型使用<String,Integer>
     使用Function接口中的方法apply,把字符串类型的整数，转换为Integer类型的整数
 */
    public static void change(String s, Function<String, Integer> fun) {
        //Integer in = fun.apply(s);
        int in = fun.apply(s);//拆箱装箱
        System.out.println(in);
    }

    public int change1(int s, Function<Integer, Integer> fun) {
        //Integer in = fun.apply(s);
        int in = fun.apply(s);//拆箱装箱
        System.out.println(in);
        return in;
    }

    /**
     * Predicate<T>断言型接口：确定T类型的对象是否满足约束，
     * 并返回boolean值，包含方法boolean test(T t)。
     */
    @Test
    public void predicateDemo1() {
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("Java");
        arrayList.add("PHP");
        arrayList.add("Python");
        arrayList.add("JavaScript");
        System.out.println("过滤前：");
        System.out.println(arrayList);

        List<String> filterResult = filterStringList(arrayList, new Predicate<String>() {
            @Override
            public boolean test(String s) {
                // 返回字符串中是否包含 P
                return s.contains("P");
            }
        });
        System.out.println("过滤后：");
        System.out.println(filterResult);
        List<String> filterResult1 = filterStringList(arrayList, s -> {
            // 返回字符串中是否包含 P
            return s.equals("Java");
        });
        System.out.println("过滤后：");
        System.out.println(filterResult1);
    }

    /**
     * 根据 Predicate 断言的结果，过滤 list 中的字符串
     *
     * @param list      待过滤字符串
     * @param predicate 提供规则的接口实例
     * @return 过滤后的列表
     */
    public static List<String> filterStringList(List<String> list, Predicate<String> predicate) {
        // 过滤后的字符串列表
        ArrayList<String> arrayList = new ArrayList<>();
        for (String string : list) {
            if (predicate.test(string)) {
                // 如果 test 是 true，则将元素加入到过滤后的列表中
                arrayList.add(string);
            }
        }
        return arrayList;
    }


    /**
     * 根据 Predicate 断言的结果，过滤 list 中的字符串
     *
     * @param list      待过滤字符串
     * @param predicate 提供规则的接口实例
     * @return 过滤后的列表
     */
    public static List<Integer> filterStringList2(List<Cat> list, Predicate<Integer> predicate) {
        // 过滤后的字符串列表
        ArrayList<Integer> arrayList = new ArrayList<>();
        for (Cat cat : list) {
            Integer aa = cat.getPrice() * cat.getWeight();

            System.out.println(aa);

        }
        return arrayList;
    }

    @Test
    public void predicateDemo3() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        List<Cat> cats = Arrays.asList(
                new Cat(1, 2, 20),
                new Cat(2, 3, 20),
                new Cat(3, 4, 20),
                new Cat(4, 5, 20)

        );
        Integer sum = list.stream()
                .reduce(0, (x, y) -> x + y);
        System.out.println(sum);
        System.out.println("----------------------------------------");

    }

    /**
     * 将id进行合并nums, sums 相加道回合并后的集合使用Java8的流进行处理
     */
    @Test
    public void merge() {
        List<Cat> list = Arrays.asList(
                new Cat(1, 2, 20),
                new Cat(2, 3, 20),
                new Cat(3, 4, 20),
                new Cat(4, 5, 20)

        );
        Map<Integer, Cat> map = new HashMap<>();
        list.stream()
                .forEach(billsNums -> {
                    Cat last = map.get(billsNums.getId());
                    if (null != last) {
                        billsNums.setPrice(billsNums.getPrice() + last.getPrice());
                        billsNums.setWeight(billsNums.getWeight() + last.getWeight());
                        map.put(billsNums.getId(), billsNums);
                    } else {
                        map.put(billsNums.getId(), billsNums);
                    }
                });
        System.out.println(map.values().stream().collect(Collectors.toList()));
        System.out.println(map);
    }

}
